#include "execution/catalog.h"
#include "execution/executor.h"
#include "storage/buffer_pool.h"
#include "storage/disk_manager.h"
#include "compiler/lexer.h"
#include "compiler/parser.h"
#include "compiler/semantic_analyzer.h"
#include "compiler/planner.h"
#include <iostream>
#include <memory>
#include <cassert>

// Helper function to print test results
void printTestResult(const std::string& testName, bool passed) {
    std::cout << (passed ? "PASS" : "FAIL") << ": " << testName << std::endl;
}

// Helper function to print execution results
void printExecutionResult(const ExecutionResult& result) {
    if (!result.success) {
        std::cout << "  Error: " << result.message << std::endl;
        return;
    }
    
    std::cout << "  Rows affected: " << result.rows.size() << std::endl;
    if (!result.rows.empty()) {
        std::cout << "  Sample data:" << std::endl;
        // Print first 3 rows
        int count = 0;
        for (const auto& row : result.rows) {
            std::cout << "    ";
            for (const auto& col : row) {
                std::cout << col << " | ";
            }
            std::cout << std::endl;
            count++;
            if (count >= 3) break;
        }
    }
}

// Helper function to execute a single SQL statement
ExecutionResult executeSingleSQL(const std::string& sql, Lexer& lexer, Parser& parser, 
                                 SemanticAnalyzer& semanticAnalyzer, Planner& planner, Executor& executor) {
    try {
        // Tokenize
        std::vector<Token> tokens = lexer.tokenize();
        
        // Parse (expecting a single statement)
        std::vector<std::unique_ptr<AST::Statement>> statements = parser.parseMultipleStatements();
        if (statements.empty()) {
            return {false, "No valid SQL statement parsed", {}};
        }
        
        // Semantic analysis
        semanticAnalyzer.analyze(statements[0]);
        
        // Create execution plan
        std::unique_ptr<Execution::PlanNode> plan = planner.createPlan(statements[0]);
        
        // Execute
        return executor.execute(plan);
    } catch (const LexerError& e) {
        return {false, std::string("Lexer error: ") + e.what(), {}};
    } catch (const ParserError& e) {
        return {false, std::string("Parser error: ") + e.what(), {}};
    } catch (const SemanticError& e) {
        return {false, std::string("Semantic error: ") + e.what(), {}};
    } catch (const std::exception& e) {
        return {false, std::string("System error: ") + e.what(), {}};
    }
}

int main() {
    std::cout << "Executor Ultimate Comprehensive Test" << std::endl;
    std::cout << "====================================" << std::endl;
    
    // Component creation
    std::unique_ptr<DiskManager> dm = std::make_unique<DiskManager>("ultimate_test.db");
    std::unique_ptr<BufferPool> bp = std::make_unique<BufferPool>(10, std::move(dm));
    std::shared_ptr<Catalog> cat = std::make_shared<Catalog>(std::move(bp));
    Executor exec(cat->getBufferPool(), cat);
    SemanticAnalyzer semanticAnalyzer(cat);
    
    std::cout << "All components created successfully." << std::endl;
    
    // Test case 1: Create table
    std::cout << "\nTest 1: Create Table" << std::endl;
    std::string createTableSQL = "CREATE TABLE students (id INT PRIMARY KEY, name VARCHAR(50), age INT, score FLOAT);";
    Lexer lexer1(createTableSQL);
    Parser parser1(lexer1.tokenize());
    Planner planner1;
    ExecutionResult createResult = executeSingleSQL(createTableSQL, lexer1, parser1, semanticAnalyzer, planner1, exec);
    printExecutionResult(createResult);
    printTestResult("Create table students", createResult.success);
    
    // Test case 2: Insert data
    std::cout << "\nTest 2: Insert Data" << std::endl;
    int insertSuccessCount = 0;
    
    std::string insertSQL1 = "INSERT INTO students VALUES (1, 'Alice', 20, 85.5);";
    Lexer lexer2_1(insertSQL1);
    Parser parser2_1(lexer2_1.tokenize());
    Planner planner2_1;
    ExecutionResult insertResult1 = executeSingleSQL(insertSQL1, lexer2_1, parser2_1, semanticAnalyzer, planner2_1, exec);
    if (insertResult1.success) insertSuccessCount++;
    
    std::string insertSQL2 = "INSERT INTO students VALUES (2, 'Bob', 22, 90.0);";
    Lexer lexer2_2(insertSQL2);
    Parser parser2_2(lexer2_2.tokenize());
    Planner planner2_2;
    ExecutionResult insertResult2 = executeSingleSQL(insertSQL2, lexer2_2, parser2_2, semanticAnalyzer, planner2_2, exec);
    if (insertResult2.success) insertSuccessCount++;
    
    std::string insertSQL3 = "INSERT INTO students VALUES (3, 'Charlie', 21, 78.5);";
    Lexer lexer2_3(insertSQL3);
    Parser parser2_3(lexer2_3.tokenize());
    Planner planner2_3;
    ExecutionResult insertResult3 = executeSingleSQL(insertSQL3, lexer2_3, parser2_3, semanticAnalyzer, planner2_3, exec);
    if (insertResult3.success) insertSuccessCount++;
    
    std::cout << "  Inserted " << insertSuccessCount << " rows" << std::endl;
    printTestResult("Insert data into students", insertSuccessCount == 3);
    
    // Test case 3: Select all data
    std::cout << "\nTest 3: Select All Data" << std::endl;
    std::string selectAllSQL = "SELECT * FROM students;";
    Lexer lexer3(selectAllSQL);
    Parser parser3(lexer3.tokenize());
    Planner planner3;
    ExecutionResult selectAllResult = executeSingleSQL(selectAllSQL, lexer3, parser3, semanticAnalyzer, planner3, exec);
    printExecutionResult(selectAllResult);
    printTestResult("Select all data from students", selectAllResult.success);
    
    // Test case 4: Select with condition
    std::cout << "\nTest 4: Select with Condition" << std::endl;
    std::string selectCondSQL = "SELECT name, score FROM students WHERE age > 20;";
    Lexer lexer4(selectCondSQL);
    Parser parser4(lexer4.tokenize());
    Planner planner4;
    ExecutionResult selectCondResult = executeSingleSQL(selectCondSQL, lexer4, parser4, semanticAnalyzer, planner4, exec);
    printExecutionResult(selectCondResult);
    printTestResult("Select with condition (age > 20)", selectCondResult.success);
    
    // Test case 5: Update data
    std::cout << "\nTest 5: Update Data" << std::endl;
    std::string updateSQL = "UPDATE students SET score = 92.5 WHERE name = 'Bob';";
    Lexer lexer5(updateSQL);
    Parser parser5(lexer5.tokenize());
    Planner planner5;
    ExecutionResult updateResult = executeSingleSQL(updateSQL, lexer5, parser5, semanticAnalyzer, planner5, exec);
    printExecutionResult(updateResult);
    
    // Verify update
    std::string verifyUpdateSQL = "SELECT score FROM students WHERE name = 'Bob';";
    Lexer lexer5_verify(verifyUpdateSQL);
    Parser parser5_verify(lexer5_verify.tokenize());
    Planner planner5_verify;
    ExecutionResult verifyUpdateResult = executeSingleSQL(verifyUpdateSQL, lexer5_verify, parser5_verify, semanticAnalyzer, planner5_verify, exec);
    bool updateVerified = false;
    if (verifyUpdateResult.success && !verifyUpdateResult.rows.empty() && !verifyUpdateResult.rows[0].empty()) {
        // Compare with possible variations in string representation of floating point numbers
        updateVerified = (verifyUpdateResult.rows[0][0] == "92.5" || verifyUpdateResult.rows[0][0] == "92.50" || verifyUpdateResult.rows[0][0] == "92.500");
    }
    std::cout << "  Verification: Bob's score is " << (updateVerified ? "92.5" : "not updated") << std::endl;
    printTestResult("Update data in students", updateResult.success && updateVerified);
    
    // Test case 6: Delete data
    std::cout << "\nTest 6: Delete Data" << std::endl;
    std::string deleteSQL = "DELETE FROM students WHERE id = 3;";
    Lexer lexer6(deleteSQL);
    Parser parser6(lexer6.tokenize());
    Planner planner6;
    ExecutionResult deleteResult = executeSingleSQL(deleteSQL, lexer6, parser6, semanticAnalyzer, planner6, exec);
    printExecutionResult(deleteResult);
    
    // Verify delete
    std::string verifyDeleteSQL = "SELECT * FROM students WHERE id = 3;";
    Lexer lexer6_verify(verifyDeleteSQL);
    Parser parser6_verify(lexer6_verify.tokenize());
    Planner planner6_verify;
    ExecutionResult verifyDeleteResult = executeSingleSQL(verifyDeleteSQL, lexer6_verify, parser6_verify, semanticAnalyzer, planner6_verify, exec);
    bool deleteVerified = verifyDeleteResult.success && verifyDeleteResult.rows.empty();
    std::cout << "  Verification: Record with id=3 " << (deleteVerified ? "was deleted" : "still exists") << std::endl;
    printTestResult("Delete data from students", deleteResult.success && deleteVerified);
    
    // Test case 7: Error handling - Duplicate primary key
    std::cout << "\nTest 7: Error Handling - Duplicate Primary Key" << std::endl;
    std::string duplicateSQL = "INSERT INTO students VALUES (1, 'Duplicate', 19, 88.0);";
    Lexer lexer7(duplicateSQL);
    Parser parser7(lexer7.tokenize());
    Planner planner7;
    ExecutionResult duplicateResult = executeSingleSQL(duplicateSQL, lexer7, parser7, semanticAnalyzer, planner7, exec);
    printExecutionResult(duplicateResult);
    printTestResult("Detect duplicate primary key", !duplicateResult.success);
    
    // Test case 8: Error handling - Invalid SQL syntax
    std::cout << "\nTest 8: Error Handling - Invalid SQL Syntax" << std::endl;
    std::string invalidSQL = "SELECT * FORM students;";  // Deliberate typo in "FROM"
    Lexer lexer8(invalidSQL);
    Parser parser8(lexer8.tokenize());
    Planner planner8;
    ExecutionResult invalidResult = executeSingleSQL(invalidSQL, lexer8, parser8, semanticAnalyzer, planner8, exec);
    printExecutionResult(invalidResult);
    printTestResult("Detect invalid SQL syntax", !invalidResult.success);
    
    // Final cleanup
    std::cout << "\nTest completed. Cleaning up test file." << std::endl;
    std::remove("ultimate_test.db");
    
    std::cout << "\nExecutor Ultimate Test Finished" << std::endl;
    return 0;
}